home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gdevpsfu.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  9.7 KB  |  350 lines

  1. /* Copyright (C) 2000 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gdevpsfu.c,v 1.4 2000/09/19 19:00:21 lpd Exp $ */
  20. /* PostScript/PDF font writing utilities */
  21. #include "memory_.h"
  22. #include <stdlib.h>        /* for qsort */
  23. #include "gx.h"
  24. #include "gserrors.h"
  25. #include "gsmatrix.h"        /* for gxfont.h */
  26. #include "gxfont.h"
  27. #include "gdevpsf.h"
  28.  
  29. /* Begin enumerating the glyphs in a font or a font subset. */
  30. private int
  31. enumerate_font_next(psf_glyph_enum_t *ppge, gs_glyph *pglyph)
  32. {
  33.     gs_font *font = ppge->font;
  34.     int index = (int)ppge->index;
  35.     int code = font->procs.enumerate_glyph(font, &index,
  36.                        ppge->glyph_space, pglyph);
  37.  
  38.     ppge->index = index;
  39.     return (index == 0 ? 1 : code < 0 ? code : 0);
  40. }
  41. private int
  42. enumerate_glyphs_next(psf_glyph_enum_t *ppge, gs_glyph *pglyph)
  43. {
  44.     if (ppge->index >= ppge->subset.size)
  45.     return 1;
  46.     *pglyph = ppge->subset.selected.list[ppge->index++];
  47.     return 0;
  48. }
  49. private int
  50. enumerate_range_next(psf_glyph_enum_t *ppge, gs_glyph *pglyph)
  51. {
  52.     if (ppge->index >= ppge->subset.size)
  53.     return 1;
  54.     *pglyph = (gs_glyph)(ppge->index++ + gs_min_cid_glyph);
  55.     return 0;
  56. }
  57. void
  58. psf_enumerate_list_begin(psf_glyph_enum_t *ppge, gs_font *font,
  59.              const gs_glyph *subset_list, uint subset_size,
  60.              gs_glyph_space_t glyph_space)
  61. {
  62.     ppge->font = font;
  63.     ppge->subset.selected.list = subset_list;
  64.     ppge->subset.size = subset_size;
  65.     ppge->glyph_space = glyph_space;
  66.     ppge->enumerate_next =
  67.     (subset_list ? enumerate_glyphs_next :
  68.      subset_size ? enumerate_range_next : enumerate_font_next);
  69.     psf_enumerate_glyphs_reset(ppge);
  70. }
  71.  
  72. /* Begin enumerating CID or TT glyphs in a subset given by a bit vector. */
  73. private int
  74. enumerate_bits_next(psf_glyph_enum_t *ppge, gs_glyph *pglyph)
  75. {
  76.     for (; ppge->index < ppge->subset.size; ppge->index++)
  77.     if (ppge->subset.selected.bits[ppge->index >> 3] & (0x80 >> (ppge->index & 7))) {
  78.         *pglyph = (gs_glyph)(ppge->index++ + gs_min_cid_glyph);
  79.         return 0;
  80.     }
  81.     return 1;
  82. }
  83. void
  84. psf_enumerate_bits_begin(psf_glyph_enum_t *ppge, gs_font *font,
  85.              const byte *subset_bits, uint subset_size,
  86.              gs_glyph_space_t glyph_space)
  87. {
  88.     ppge->font = font;
  89.     ppge->subset.selected.bits = subset_bits;
  90.     ppge->subset.size = subset_size;
  91.     ppge->glyph_space = glyph_space;
  92.     ppge->enumerate_next =
  93.     (subset_bits ? enumerate_bits_next :
  94.      subset_size ? enumerate_range_next : enumerate_font_next);
  95.     psf_enumerate_glyphs_reset(ppge);
  96. }
  97.  
  98. /* Reset a glyph enumeration. */
  99. void
  100. psf_enumerate_glyphs_reset(psf_glyph_enum_t *ppge)
  101. {
  102.     ppge->index = 0;
  103. }
  104.  
  105. /* Enumerate the next glyph in a font or a font subset. */
  106. /* Return 0 if more glyphs, 1 if done, <0 if error. */
  107. int
  108. psf_enumerate_glyphs_next(psf_glyph_enum_t *ppge, gs_glyph *pglyph)
  109. {
  110.     return ppge->enumerate_next(ppge, pglyph);
  111. }
  112.  
  113. /*
  114.  * Get the set of referenced glyphs (indices) for writing a subset font.
  115.  * Does not sort or remove duplicates.
  116.  */
  117. int
  118. psf_subset_glyphs(gs_glyph glyphs[256], gs_font *font, const byte used[32])
  119. {
  120.     int i, n;
  121.  
  122.     for (i = n = 0; i < 256; ++i)
  123.     if (used[i >> 3] & (1 << (i & 7))) {
  124.         gs_glyph glyph = font->procs.encode_char(font, (gs_char)i,
  125.                              GLYPH_SPACE_INDEX);
  126.  
  127.         if (glyph != gs_no_glyph)
  128.         glyphs[n++] = glyph;
  129.     }
  130.     return n;
  131. }
  132.  
  133. /*
  134.  * Add composite glyph pieces to a list of glyphs.  Does not sort or
  135.  * remove duplicates.  max_pieces is the maximum number of pieces that a
  136.  * single glyph can have: if this value is not known, the caller should
  137.  * use max_count.
  138.  */
  139. int
  140. psf_add_subset_pieces(gs_glyph *glyphs, uint *pcount, uint max_count,
  141.                uint max_pieces, gs_font *font)
  142. {
  143.     uint i;
  144.     uint count = *pcount;
  145.  
  146.     for (i = 0; i < count; ++i) {
  147.     gs_glyph_info_t info;
  148.     int code;
  149.  
  150.     if (count + max_pieces > max_count) {
  151.         /* Check first to make sure there is enough room. */
  152.         code = font->procs.glyph_info(font, glyphs[i], NULL,
  153.                       GLYPH_INFO_NUM_PIECES, &info);
  154.         if (code < 0)
  155.         continue;
  156.         if (count + info.num_pieces > max_count)
  157.         return_error(gs_error_rangecheck);
  158.     }
  159.     info.pieces = &glyphs[count];
  160.     code = font->procs.glyph_info(font, glyphs[i], NULL,
  161.                       GLYPH_INFO_NUM_PIECES |
  162.                       GLYPH_INFO_PIECES, &info);
  163.     if (code >= 0)
  164.         count += info.num_pieces;
  165.     }
  166.     *pcount = count;
  167.     return 0;
  168. }
  169.  
  170. /*
  171.  * Sort a list of glyphs and remove duplicates.  Return the number of glyphs
  172.  * in the result.
  173.  */
  174. private int
  175. compare_glyphs(const void *pg1, const void *pg2)
  176. {
  177.     gs_glyph g1 = *(const gs_glyph *)pg1, g2 = *(const gs_glyph *)pg2;
  178.  
  179.     return (g1 < g2 ? -1 : g1 > g2 ? 1 : 0);
  180. }
  181. int
  182. psf_sort_glyphs(gs_glyph *glyphs, int count)
  183. {
  184.     int i, n;
  185.  
  186.     qsort(glyphs, count, sizeof(*glyphs), compare_glyphs);
  187.     for (i = n = 0; i < count; ++i)
  188.     if (i == 0 || glyphs[i] != glyphs[i - 1])
  189.         glyphs[n++] = glyphs[i];
  190.     return n;
  191. }
  192.  
  193. /*
  194.  * Return the index of a given glyph in a sorted list of glyphs, or -1
  195.  * if the glyph is not present.
  196.  */
  197. int
  198. psf_sorted_glyphs_index_of(const gs_glyph *glyphs, int count, gs_glyph glyph)
  199. {
  200.     int lo = 0, hi = count - 1;
  201.  
  202.     if (hi < 0)
  203.     return -1;
  204.     if (glyph < glyphs[0] || glyph > glyphs[hi])
  205.     return -1;
  206.     /*
  207.      * Loop invariants: hi > lo;
  208.      * glyphs[lo] <= glyph <= glyphs[hi].
  209.      */
  210.     while (hi - lo > 1) {
  211.     int mid = (lo + hi) >> 1;
  212.  
  213.     if (glyph >= glyphs[mid])
  214.         lo = mid;
  215.     else
  216.         hi = mid;
  217.     }
  218.     return (glyph == glyphs[lo] ? lo : glyph == glyphs[hi] ? hi : -1);
  219. }
  220. /* Determine whether a sorted list of glyphs includes a given glyph. */
  221. bool
  222. psf_sorted_glyphs_include(const gs_glyph *glyphs, int count, gs_glyph glyph)
  223. {
  224.     return psf_sorted_glyphs_index_of(glyphs, count, glyph) >= 0;
  225. }
  226.  
  227. /* Check that all selected glyphs can be written. */
  228. int
  229. psf_check_outline_glyphs(gs_font_base *pfont, psf_glyph_enum_t *ppge,
  230.              glyph_data_proc_t glyph_data)
  231. {
  232.     uint members = GLYPH_INFO_WIDTH0 << pfont->WMode;
  233.     gs_glyph glyph;
  234.     int code;
  235.  
  236.     while ((code = psf_enumerate_glyphs_next(ppge, &glyph)) != 1) {
  237.     gs_const_string gdata;
  238.     gs_font_type1 *ignore_font;
  239.     gs_glyph_info_t info;
  240.  
  241.     if (code < 0)
  242.         return code;
  243.     code = glyph_data(pfont, glyph, &gdata, &ignore_font);
  244.     /*
  245.      * If the glyph isn't defined by a CharString, glyph_data will
  246.      * return a typecheck error.  But if there's merely a glyph in
  247.      * in the Encoding that isn't defined, glyph_data will return an
  248.      * undefined error, which is OK.
  249.      */
  250.     if (code < 0) {
  251.         if (code == gs_error_undefined)
  252.         continue;
  253.         return code;
  254.     }
  255.     /*
  256.      * If the font has a CDevProc or calls a non-standard OtherSubr,
  257.      * glyph_info will return a rangecheck error.
  258.      */
  259.     code = pfont->procs.glyph_info((gs_font *)pfont, glyph, NULL,
  260.                        members, &info);
  261.     if (code < 0)
  262.         return code;
  263.     }
  264.     return 0;
  265. }
  266.  
  267. /* Gather glyph information for a Type 1 or Type 2 font. */
  268. int
  269. psf_get_outline_glyphs(psf_outline_glyphs_t *pglyphs, gs_font_base *pfont,
  270.                gs_glyph *orig_subset_glyphs, uint orig_subset_size,
  271.                glyph_data_proc_t glyph_data)
  272. {
  273.     gs_glyph notdef = gs_no_glyph;
  274.     gs_glyph *subset_glyphs = orig_subset_glyphs;
  275.     uint subset_size = orig_subset_size;
  276.  
  277.     if (subset_glyphs) {
  278.     if (subset_size > countof(pglyphs->subset_data))
  279.         return_error(gs_error_limitcheck);
  280.     memcpy(pglyphs->subset_data, orig_subset_glyphs,
  281.            sizeof(gs_glyph) * subset_size);
  282.     subset_glyphs = pglyphs->subset_data;
  283.     }
  284.  
  285.     {
  286.     /*
  287.      * Make sure that this font can be written out.  Specifically, it
  288.      * must have no CharStrings defined by PostScript procedures, no
  289.      * non-standard OtherSubrs, and no CDevProc.
  290.      */
  291.     psf_glyph_enum_t genum;
  292.     int code;
  293.  
  294.     psf_enumerate_glyphs_begin(&genum, (gs_font *)pfont, subset_glyphs,
  295.                     (subset_glyphs ? subset_size : 0),
  296.                     GLYPH_SPACE_NAME);
  297.     code = psf_check_outline_glyphs(pfont, &genum, glyph_data);
  298.     if (code < 0)
  299.         return code;
  300.     }
  301.  
  302.     {
  303.     /*
  304.      * Detect the .notdef glyph, needed for subset fonts and to
  305.      * eliminate unnecessary Encoding assignments.
  306.      */
  307.     psf_glyph_enum_t genum;
  308.     gs_glyph glyph;
  309.     int code;
  310.  
  311.     psf_enumerate_glyphs_begin(&genum, (gs_font *)pfont, NULL, 0,
  312.                     GLYPH_SPACE_NAME);
  313.     while ((code = psf_enumerate_glyphs_next(&genum, &glyph)) != 1) {
  314.         uint namelen;
  315.         const char *namestr =
  316.         (*pfont->procs.callbacks.glyph_name)(glyph, &namelen);
  317.  
  318.         if (namestr && namelen == 7 && !memcmp(namestr, ".notdef", 7)) {
  319.         notdef = glyph;
  320.         break;
  321.         }
  322.     }
  323.     }
  324.  
  325.     if (subset_glyphs) {
  326.     /*
  327.      * For subset fonts, we must ensure that characters referenced
  328.      * by seac are also included.  Note that seac creates at most
  329.      * 2 pieces.
  330.      */
  331.     int code = psf_add_subset_pieces(subset_glyphs, &subset_size,
  332.                       countof(pglyphs->subset_data) - 1, 2,
  333.                       (gs_font *)pfont);
  334.  
  335.     if (code < 0)
  336.         return code;
  337.     /* Subset fonts require .notdef. */
  338.     if (notdef == gs_no_glyph)
  339.         return_error(gs_error_rangecheck);
  340.     /* Sort the glyphs now.  Make sure .notdef is included. */
  341.     subset_glyphs[subset_size++] = notdef;
  342.     subset_size = psf_sort_glyphs(subset_glyphs, subset_size);
  343.     }
  344.  
  345.     pglyphs->notdef = notdef;
  346.     pglyphs->subset_glyphs = subset_glyphs;
  347.     pglyphs->subset_size = subset_size;
  348.     return 0;
  349. }
  350.